/**
 *Copyright (c) 2024 watereyes
 * safetymanagement is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan
 * PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */
package com.koron.scene.service.impl;


import com.koron.common.bean.DepartmentTreeBean;
import com.koron.common.bean.StaffBean;
import com.koron.common.domain.DataBean;
import com.koron.common.generator.DefaultIdGenerator;
import com.koron.common.web.Util;
import com.koron.hiddendanger.domain.HiddenDangerDiscovery;
import com.koron.hiddendanger.service.api.HiddenDangerDiscoveryService;
import com.koron.risk.bean.CorpBean;
import com.koron.risk.mapper.CorpManagementMapper;
import com.koron.risk.service.api.GridNodeService;
import com.koron.scene.bean.CalibrationHistoryView;
import com.koron.scene.bean.CheckResultView;
import com.koron.scene.domain.Device;
import com.koron.scene.mapper.DeviceMapper;
import com.koron.scene.service.api.DeviceService;
import com.koron.scene.utils.BusinessCode;
import com.koron.system.domain.DictData;
import com.koron.system.domain.Message;
import com.koron.system.mapper.MessageMapper;
import com.koron.system.service.api.DictDataService;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.koron.ebs.mybatis.SessionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.swan.bean.MessageBean;

import java.io.InputStream;
import java.lang.reflect.Field;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.koron.common.emailandsms.SendMsg.sendSMS;
import static com.koron.scene.utils.ExcelUtil.getCellValue;

@Service
@EnableScheduling
public class DeviceServiceImpl implements DeviceService {

    private final static  Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class);

    @Autowired
    private DictDataService dataService;

    @Autowired
    private Util util;

    @Autowired
    private HiddenDangerDiscoveryService dangerService;

    @Autowired
    private GridNodeService nodeService;

    @Override
    public DataBean<Device> fetchDevices(String corpCode, String gridCode, String deviceName, String deviceTypeId, String deptName, String checkEmployeeName, Timestamp calibrationExpiredDate, Integer status, Integer start, Integer rows,String keyword) {
        if (logger.isDebugEnabled()) {
            logger.debug("gridCode = {}, deviceName = {}, checkEmployeeName = {}, calibrationExpiredDate = {}", gridCode, deviceName, checkEmployeeName, calibrationExpiredDate);
        }
        try (SessionFactory factory = new SessionFactory()) {
            String codes = util.getCodes(corpCode);
            DeviceMapper mapper = factory.getMapper(DeviceMapper.class);
            List<Device> devices = mapper.queryByConditionAll(codes, gridCode, deviceName, deviceTypeId, deptName, checkEmployeeName, calibrationExpiredDate, status, start, rows,keyword);
            Integer total = mapper.countByConditionAll(codes, gridCode, deviceName, deviceTypeId, deptName, checkEmployeeName, calibrationExpiredDate, status,keyword);
            if (devices != null && !devices.isEmpty()) {
                Map<String, DictData> cacheMap = dataService.getCacheMap();
//                CorpBean corpBean = factory.getMapper(CorpManagementMapper.class).get(corpCode);
                Map<String, String> corpMap = util.getCorpMap();
                if (corpMap != null) {
                    devices.forEach(device -> {
                        device.setCorpName(corpMap.get(device.getCorpCode()));
                        if (StringUtils.isNotBlank(device.getDeviceTypeId())) {
                            DictData dictData = cacheMap.get(device.getDeviceTypeId());
                            device.setDeviceTypeName(dictData != null ? dictData.getDictLabel() : "");
                        }
                        if (StringUtils.isNotBlank(device.getDeptCode())) {
                            MessageBean<?> messageBean = util.depttree(device.getDeptCode(), 0);
                            List list = (List) messageBean.getData();
                            DepartmentTreeBean bean = (DepartmentTreeBean) list.get(0);
                            device.setDeptName(bean.getName());
                        }
                    });
                }
            }
            DataBean<Device> dataBean = new DataBean<>();
            dataBean.setList(devices);
            if (start != null && rows != null) {
                dataBean.setPageSize(rows);
                dataBean.setTotalNumber(total);
                dataBean.setTotalPage(total > rows ? (total % rows == 0 ? total / rows : total / rows + 1) : 1);
                dataBean.setPageNo(start / rows + 1);
            }
            return dataBean;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
        return null;
    }

    @Override
    public Device fetchOne(String id) {
        if (logger.isDebugEnabled()) {
            logger.debug("id = {}", id);
        }
        try (SessionFactory factory = new SessionFactory()) {
            Device device = factory.getMapper(DeviceMapper.class).queryOne(id);
            if (device != null && StringUtils.isNotBlank(device.getCorpCode())) {
                CorpBean corpBean = factory.getMapper(CorpManagementMapper.class).get(device.getCorpCode());
                if (corpBean != null) {
                    device.setCorpName(corpBean.getCorpName());
                    Map<String, DictData> cacheMap = dataService.getCacheMap();
                    if (StringUtils.isNotBlank(device.getDeviceTypeId())) {
                        DictData dictData = cacheMap.get(device.getDeviceTypeId());
                        device.setDeviceTypeName(dictData != null ? dictData.getDictLabel() : "");
                    }
                    if (StringUtils.isNotBlank(device.getDeptCode())) {
                        MessageBean<?> messageBean = util.depttree(device.getDeptCode(), 0);
                        List list = (List) messageBean.getData();
                        DepartmentTreeBean bean = (DepartmentTreeBean) list.get(0);
                        device.setDeptName(bean.getName());
                    }
                }
            }
            return device;
        }
    }

    @Override
    public Boolean batchDetele(List<String> idList) {
        try (SessionFactory factory = new SessionFactory()) {
            return factory.getMapper(DeviceMapper.class).batchDetele(idList) >= 0;
        }
    }

    @Override
    public Integer persist(Device device) {
        try (SessionFactory factory = new SessionFactory()) {
            Integer start = null, rows = null, status = null;
            String checkEmployeeName = null, deviceTypeId = null, deptName = null;
            Timestamp calibrationExpiredDate = null;
            Device dest = null;
            DeviceMapper mapper = factory.getMapper(DeviceMapper.class);
            List<Device> devices = mapper.queryByCondition(device.getCorpCode(), device.getGridCode(), device.getDeviceName(), deviceTypeId, deptName, checkEmployeeName, calibrationExpiredDate, status, start, rows);
            if (devices != null && !devices.isEmpty()) {
                devices = devices.stream().filter(d -> d.getDeviceName().equals(device.getDeviceName())).collect(Collectors.toList());
                dest = !devices.isEmpty() ? devices.get(0) : null;
            }
            if (StringUtils.isBlank(device.getId())) {
                if (dest != null) {
                    return BusinessCode.DEVICE_NAME_DUP.getCode();
                }
                device.setId(DefaultIdGenerator.getInstance().generateLongId());
                if (mapper.insert(device) > 0) {
                    return BusinessCode.SUCCESS.getCode();
                }
            } else {
                if (dest != null && !dest.getId().equals(device.getId())) {
                    return BusinessCode.DEVICE_NAME_DUP.getCode();
                }
                if (mapper.update(device) > 0) {
                    return BusinessCode.SUCCESS.getCode();
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
        return BusinessCode.EXCEPTION.getCode();
    }


    @Override
    public DataBean<CheckResultView> checkHistory(String deviceName, String deviceId, Integer start, Integer rows) {
        try (SessionFactory factory = new SessionFactory()) {
            DeviceMapper mapper = factory.getMapper(DeviceMapper.class);
            List<CheckResultView> views = mapper.queryAssociatedCheck(deviceId, start, rows);
            Integer total = mapper.countAssociatedCheck(deviceId);
            if (views != null && !views.isEmpty()) {
                views.forEach(v -> v.setDeviceName(deviceName));
            }
            DataBean<CheckResultView> dataBean = new DataBean<>();
            dataBean.setList(views);
            if (start != null && rows != null) {
                dataBean.setTotalNumber(total);
                dataBean.setPageSize(rows);
                dataBean.setTotalPage(total > rows ? (total % rows == 0 ? total / rows : total / rows + 1) : 1);
                dataBean.setPageNo(start / rows + 1);
            }
            return dataBean;
        }
    }


    @Override
    public DataBean<CalibrationHistoryView> calibrationHistory(String deviceName, String deviceId, Integer start, Integer rows) {
        try (SessionFactory factory = new SessionFactory()) {
            DeviceMapper mapper = factory.getMapper(DeviceMapper.class);
            List<CalibrationHistoryView> views = mapper.queryAssociatedCalibration(deviceId, start, rows);
            Integer total = mapper.countAssociatedCalibration(deviceId);
            if (views != null && !views.isEmpty()) {
                views.forEach(v -> v.setDeviceName(deviceName));
            }
            DataBean<CalibrationHistoryView> dataBean = new DataBean<>();
            dataBean.setList(views);
            if (start != null && rows != null) {
                dataBean.setTotalNumber(total);
                dataBean.setPageSize(rows);
                dataBean.setPageNo(start / rows + 1);
                dataBean.setTotalPage(total > rows ? (total % rows == 0 ? total / rows : total / rows + 1) : 1);
            }
            return dataBean;
        }
    }

    @Override
    public List<HiddenDangerDiscovery> getHiddenDangers(List<String> idList) {
        MessageBean<List<HiddenDangerDiscovery>> messageBean = dangerService.queryDangerByIdList(idList);
        if (messageBean == null || messageBean.getData() == null) {
            return Collections.EMPTY_LIST;
        }
        return messageBean.getData();
    }

    @Override
    public MessageBean<?> importExcel(StaffBean user, MultipartFile file) {
        MessageBean<String> msg = MessageBean.create(BusinessCode.SUCCESS.getCode(), "导入成功", String.class);
        SessionFactory factory = new SessionFactory();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<Device> list = new ArrayList<>();
        List<Device> addList = new ArrayList<>();
        List<Device> updateList = new ArrayList<>();
        try {
            InputStream inputStream = file.getInputStream();
            XSSFWorkbook workbook = new XSSFWorkbook(inputStream);
            XSSFSheet sheet = workbook.getSheetAt(0);
            if (sheet == null) {
                msg.setDescription(BusinessCode.FAILURE.getDescription());
                msg.setCode(BusinessCode.FAILURE.getCode());
                return msg;
            }
            // 获取excel表格行数
            int rows = sheet.getPhysicalNumberOfRows();
            // 从第三行开始读取数据
            for (int i = 3; i < rows; i++) {
                Device device = new Device();
                XSSFRow row = sheet.getRow(i);
                String id = getCellValue(row.getCell(0));
                String corpName = getCellValue(row.getCell(1));
                String deptName = getCellValue(row.getCell(2));
                String gridName = getCellValue(row.getCell(3));
                String deviceName = getCellValue(row.getCell(4));
                String deviceCode = getCellValue(row.getCell(5));
                String deviceType = getCellValue(row.getCell(6));
                String designationParam = getCellValue(row.getCell(7));
                String status = getCellValue(row.getCell(8));
                String responsibleEmployeeName = getCellValue(row.getCell(9));
                String checkEmployeeName = getCellValue(row.getCell(10));
                String calibrationExpiredDate = getCellValue(row.getCell(11));
                if (!StringUtils.isEmpty(id)) {
                    device.setId(id);
                }
                if (!StringUtils.isEmpty(corpName)) {
                    device.setCorpName(corpName);
                }
                if (!StringUtils.isEmpty(deptName)) {
                    device.setDeptName(deptName);
                }
                if (!StringUtils.isEmpty(gridName)) {
                    device.setGridName(gridName);
                }
                if (!StringUtils.isEmpty(deviceName)) {
                    device.setDeviceName(deviceName);
                }
                if (!StringUtils.isEmpty(deviceCode)) {
                    device.setDeviceCode(deviceCode);
                }
                if (!StringUtils.isEmpty(deviceType)) {
                    device.setDeviceTypeName(deviceType);
                }
                if (!StringUtils.isEmpty(designationParam)) {
                    device.setDesignationParam(designationParam);
                }
                if (!StringUtils.isEmpty(status)) {
                    device.setStatus(("正常").equals(status) ? 1 : 0);
                }
                if (!StringUtils.isEmpty(responsibleEmployeeName)) {
                    device.setResponsibleEmployeeName(responsibleEmployeeName.split("_")[0]);
                }
                if (!StringUtils.isEmpty(checkEmployeeName)) {
                    device.setCheckEmployeeName(checkEmployeeName.split("_")[0]);
                }
                if (!StringUtils.isEmpty(calibrationExpiredDate)) {
                    Date date = excelDateUtil(calibrationExpiredDate);
                    String expiredDate = null;
                    if (null != date) {
                        expiredDate = format.format(date);
                    }
                    if (null != expiredDate) {
                        // 由于Timestamp.valueOf(format)的值必须是yyyy-MM-dd HH:mm:ss 格式，提前转一次
                        device.setCalibrationExpiredDate(Timestamp.valueOf(expiredDate));
                    }
                }
                if (!checkObjAllFieldsIsNull(device)) {
                    list.add(device);
                }
            }
            // 获取组织架构
            MessageBean<?> orgTree = util.getOrgTree();
            List<DepartmentTreeBean> departmentTreeBeanList = (List<DepartmentTreeBean>) orgTree.getData();
            for (Device device : list) {
                // 根据公司名称过滤
                List<DepartmentTreeBean> treeBeanList = departmentTreeBeanList.stream().filter(departmentTreeBean -> departmentTreeBean.getName().equals(device.getCorpName())).collect(Collectors.toList());
                if (null != treeBeanList && treeBeanList.size() > 0) {
                    device.setCorpCode(treeBeanList.get(0).getDepartmentCode());
                    List<DepartmentTreeBean> departmentTreeBeans = departmentTreeBeanList.stream().filter(departmentTreeBean -> departmentTreeBean.getName().equals(device.getDeptName())).collect(Collectors.toList());
                    device.setDeptCode(null != departmentTreeBeans ? departmentTreeBeans.get(0).getDepartmentCode() : null);
                    // 根据网格名称去匹配网格code
                    if (StringUtils.isNotEmpty(device.getGridName())) {
                        // 先确定网格名称是否属于组织数据
                        List<DepartmentTreeBean> treeBeans = departmentTreeBeanList.stream().filter(dept -> device.getGridName().equals(dept.getName())).collect(Collectors.toList());
                        if (null != treeBeans && treeBeans.size() > 0) {
                            device.setGridCode(treeBeans.get(0).getDepartmentCode());
                        } else {
                            //获取网格数据
                            MessageBean<?> gridListByName = nodeService.appGetGridByName(device.getCorpCode(), device.getGridName());
                            List<Map> gridList = (List) gridListByName.getData();
                            if (null != gridList && gridList.size() > 0) {
                                String gridCode = gridList.get(0).get("code").toString();
                                device.setGridCode(gridCode);
                            }
                        }
                    }
                    device.setDesignationParam(StringUtils.isEmpty(device.getDesignationParam()) ? "标准" : device.getDesignationParam());
                    device.setStatus(null == device.getStatus() ? 1 : device.getStatus());
                    DictData dictData = dataService.matchDictData("现场管理设备类型", device.getDeviceTypeName());
                    if (null != dictData) {
                        device.setDeviceTypeId(dictData.getId());
                    }
                    // 根据检查负责人姓名查找人员信息
                    Map map = (Map) util.getStaffAndDeptFuzzyQuery(device.getCheckEmployeeName()).getData();
                    List<StaffBean> staffList = (List<StaffBean>) map.get("staffs");
                    if (null != staffList && staffList.size() > 0) {
                        device.setCheckEmployeeCode(staffList.get(0).getCode());
                    }
                    // 根据设备负责人姓名查找人员信息
                    Map map1 = (Map) util.getStaffAndDeptFuzzyQuery(device.getResponsibleEmployeeName()).getData();
                    List<StaffBean> staffBeanList = (List<StaffBean>) map1.get("staffs");
                    if (null != staffBeanList && staffBeanList.size() > 0) {
                        device.setResponsibleEmployeeCode(staffBeanList.get(0).getCode());
                    }
                    if (StringUtils.isNotEmpty(device.getId())) {
                        Device device1 = factory.getMapper(DeviceMapper.class).queryOne(device.getId());
                        if (null != device1) {
                            device.setUpdateTime(new Date());
                            device.setUpdateUser(user.getCode());
                            device.setUpdateUserName(user.getName());
                            device.setRemark("导入修改");
                            updateList.add(device);
                        } else {
                            device.setId(DefaultIdGenerator.getInstance().generateLongId());
                            device.setAddTime(new Date());
                            device.setAddUser(user.getCode());
                            device.setAddUserName(user.getName());
                            device.setRemark("导入新增");
                            addList.add(device);
                        }
                    } else {
                        device.setId(DefaultIdGenerator.getInstance().generateLongId());
                        device.setAddTime(new Date());
                        device.setAddUser(user.getCode());
                        device.setAddUserName(user.getName());
                        device.setRemark("导入新增");
                        addList.add(device);
                    }
                } else {
                    logger.info("未匹配到" + device.getCorpName() + "的公司信息，无法导入");
                }
            }
            if (null != addList && addList.size() > 0) {
                Integer value = factory.getMapper(DeviceMapper.class).batchInsert(addList);
            }
            if (null != updateList && updateList.size() > 0) {
                updateList.forEach(bean -> {
                    Integer value = factory.getMapper(DeviceMapper.class).update(bean);
                });
            }
            factory.close();
            return msg;
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
            logger.error(e.getMessage(),e);
            if (null != factory) {
                factory.close(false);
            }
            msg.setCode(BusinessCode.FAILURE.getCode());
            msg.setDescription("导入失败");
            return msg;
        } finally {
            if (factory != null) {
                factory.close();
            }
        }

    }

    /**
     * 判断对象及属性是否为空
     *
     * @param object
     * @return
     */
    public static boolean checkObjAllFieldsIsNull(Object object) {
        if (null == object) {
            return true;
        }
        try {
            for (Field f : object.getClass().getDeclaredFields()) {
                f.setAccessible(true);
                if (f.get(object) != null && StringUtils.isNotBlank(f.get(object).toString())) {
                    return false;
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
        return true;
    }


    /**
     * 将excel导入的日期转换成Date
     *
     * @param dateStr
     * @return
     */
    public static Date excelDateUtil(String dateStr) {
        Date date = null;
        try {
            if (!StringUtils.isEmpty(dateStr)) {
                date = stringToDate(dateStr, "yyyy/MM/dd");
                if (null == date) {
                    date = stringToDate(dateStr, "yyyy-MM-dd");
                }
                if (null == date) {
                    date = stringToDate(dateStr, "yyyy年MM月dd日");
                }
                if (null == date) {
                    // 前面日期都转换失败，默认excel中为日期格式
                    date = HSSFDateUtil.getJavaDate(Double.parseDouble(dateStr));
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(),e);
        }
        return date;
    }


    public static Date stringToDate(String dateStr, String simple) {
        SimpleDateFormat sdf = new SimpleDateFormat(simple);
        try {
            return sdf.parse(dateStr);
        } catch (Exception e) {
            return null;
        }
    }


    /**
     * 设备台账到期提醒，到期前三个月发送系统消息，到期前一个月发送短信通知(仅发送一次)
     * 每天上午九点执行一次
     */

    @Scheduled(cron = "0 0 9 * * ?")
    public void executeCronJob() {
        // 处理距离有效期小于等于3个月且未发送系统消息提醒的设备数据
        sendInnerMessage();
        // 处理距离有效期小于等于1个月且未发送短信提醒通知的设备数据
        sendShortMessage();
    }

    public void sendInnerMessage() {
        logger.info("------------定时任务(设备台账到期提醒，发送系统消息通知)开始执行------------");
        SessionFactory factory = new SessionFactory();
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
            // 计算当前时间延后3个月的时间值
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH, 3);
            Date date = calendar.getTime();
            DeviceMapper mapper = factory.getMapper(DeviceMapper.class);
            // 获取所有设备
            List<Device> beanList = mapper.queryAll();
            if (null != beanList && beanList.size() > 0) {
                Map<String, String> corpMap = util.getCorpMap();
                beanList.forEach(device -> device.setCorpName(corpMap.get(device.getCorpCode())));
            }
            // 存放所有要发送短信、通知的设备id
            List<String> idList = new ArrayList<>();
            // 发送系统消息的设备数据
            List<Device> innerMsgDevice = new ArrayList<>();
            if (beanList != null && beanList.size() > 0) {
                //   获取所有距离有效期小于3个月且未发送提醒通知的设备数据
                innerMsgDevice = beanList.stream().filter(bean -> null != bean.getCalibrationExpiredDate() && bean.getCalibrationExpiredDate().before(date)).filter(bean -> bean.getNoticeState() != 1 && bean.getNoticeState() != 2).collect(Collectors.toList());
            }
            // 给距有效期小于3个月的发送系统消息通知
            if (null != innerMsgDevice && innerMsgDevice.size() > 0) {
                List<Message> messageList = new ArrayList<>();
                // 去发送系统消息通知
                for (Device bean : innerMsgDevice) {
                    // 获取设备责任人code
                    String userCode = bean.getResponsibleEmployeeCode();
                    if (StringUtils.isNotEmpty(userCode)) {
                        StringBuffer sb = new StringBuffer();
                        sb.append("请注意，");
                        if (StringUtils.isNotEmpty(bean.getCorpName())) {
                            sb.append("在" + bean.getCorpName() + "单位下，");
                        }
                        sb.append("有一台您负责的名为：“" + bean.getDeviceName() + "”的设备将于：" +
                                format.format(bean.getCalibrationExpiredDate()) + "到期,请及时检查更新");
                        Message message = new Message();
                        message.setId(DefaultIdGenerator.getInstance().generateLongId());
                        message.setAddTime(bean.getUpdateTime());
                        message.setIsRemove(0);
                        message.setIsRead(0);
                        message.setAddUser(bean.getUpdateUserName());
                        message.setUpdateUser(bean.getUpdateUserName());
                        message.setUpdateTime(bean.getUpdateTime());
                        message.setTitle("您有一台设备即将到期");
                        message.setContent(sb.toString());
                        message.setReceiverCode(userCode);
                        messageList.add(message);
                        idList.add(bean.getId());
                    }
                }
                if (null != messageList && messageList.size() > 0) {
                    factory.getMapper(MessageMapper.class).batchInsert(messageList);
                }
            }
            if (idList.size() > 0) {
                mapper.batchUpdateNoticeState(idList, 1);
            }
            factory.close();
        } catch (Exception e) {
            factory.close(false);
            logger.error(e.getMessage(),e);
            logger.error("定时任务：设备台账到期提醒，发送系统消息通知失败", e);
        } finally {
            if (null != factory) {
                factory.close();
            }
        }
        logger.info("------------定时任务(设备台账到期提醒，发送系统消息通知)执行结束------------");
    }

    public void sendShortMessage() {
        logger.info("------------定时任务(设备台账到期提醒，发送短信通知)开始执行------------");
        SessionFactory factory = new SessionFactory();
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日");
            // 计算当前时间延后3个月的时间值
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MONTH, 1);
            Date date = calendar.getTime();
            DeviceMapper mapper = factory.getMapper(DeviceMapper.class);
            // 获取所有设备
            List<Device> beanList = mapper.queryAll();
            if (null != beanList && beanList.size() > 0) {
                Map<String, String> corpMap = util.getCorpMap();
                beanList.forEach(device -> device.setCorpName(corpMap.get(device.getCorpCode())));
            }
            // 存放所有要发送短信、通知的设备id
            List<String> idList = new ArrayList<>();
            // 发送短信的设备数据
            List<Device> messageDevice = new ArrayList<>();
            if (beanList != null && beanList.size() > 0) {
                //   获取所有距离有效期小于1个月且未发送提醒通知的设备数据
                messageDevice = beanList.stream().filter(bean -> null != bean.getCalibrationExpiredDate() && bean.getCalibrationExpiredDate().before(date)).filter(bean -> bean.getNoticeState() != 2).collect(Collectors.toList());
            }
            // 给距有效期小于1个月的发送短信通知
            if (null != messageDevice && messageDevice.size() > 0) {
                // 去发生短信
                for (Device bean : messageDevice) {
                    // 获取获取设备责任人code
                    String userCode = bean.getResponsibleEmployeeCode();
                    List<StaffBean> staffBeanList = (List<StaffBean>) util.staff(userCode, null).getData();
                    if (null != staffBeanList && staffBeanList.size() > 0) {
                        // 获取手机号
                        String mobile = staffBeanList.get(0).getMobile();
                        String name = staffBeanList.get(0).getName();
                        // 短信内容
                        StringBuffer sb = new StringBuffer();
                        sb.append("请注意，");
                        if (StringUtils.isNotEmpty(bean.getCorpName())) {
                            sb.append("在" + bean.getCorpName() + "单位下，");
                        }
                        sb.append("有一台您负责的名为：“" + bean.getDeviceName() + "”的设备将于：" +
                                format.format(bean.getCalibrationExpiredDate()) + "到期,请及时检查更新");
                        // 发送短信
                        if (StringUtils.isNotEmpty(mobile)) {
                            sendSMS(mobile, sb.toString());
                        } else {
                            logger.info("未找到" + name + "的手机号，未发送通知短信");
                        }
                    }
                    idList.add(bean.getId());
                }
            }
            if (idList.size() > 0) {
                mapper.batchUpdateNoticeState(idList, 2);
            }
            factory.close();
        } catch (Exception e) {
            factory.close(false);
            logger.error(e.getMessage(),e);
            logger.error("定时任务：设备台账到期提醒，发送短信通知出错", e);
        } finally {
            if (null != factory) {
                factory.close();
            }
        }
        logger.info("------------定时任务(设备台账到期提醒，发送短信通知)执行结束------------");
    }
}
